<?php
namespace app\home\service;
use QL\QueryList;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;


class DoubanService{
    /**
     * 电影列表-接口
     * @var string
     */
    const API_LIST = 'https://movie.douban.com/j/search_subjects?type={type}&tag={tag}&sort={sort}&page_limit={size}&page_start={page_start}&playable={playable}';

    /**
     * 电影详情-接口
     * @var string
     */
    const API_DETAIL = 'https://movie.douban.com/subject/{id}/';

    /**
     * 电影图片-接口
     * @var string
     */
    const API_DETAIL_PHOTOS = 'https://movie.douban.com/subject/{id}/photos?type={type}';

    /**
     * 电影搜索建议
     * @var string
     */
    const API_SEARCH_SUGGEST = 'https://movie.douban.com/j/subject_suggest?q={q}&type=movie';

    /**
     * 电影搜索建议
     * @var string
     */
    const API_PLAY_URL_JS = 'https://img3.doubanio.com/misc/mixed_static/{key}.js';

    /**
     * 电影排行榜
     * @var string
     */
    const API_CHART_LIST = 'https://movie.douban.com/chart';

    static $sort_type = ['recommend' => '按热度排序', 'time' => '按时间排序', 'rank' => '按评价排序'];
    static $tag = array('热门','最新','经典','可播放','豆瓣高分','冷门佳片','华语','欧美','韩国', '日本','动作','喜剧','爱情','科幻','悬疑','恐怖','文艺');
    static $photos_type = ['S'=>'剧照',];

    public $error = '';
    public $last_request_url = '';



    /**
     * 电影搜索建议列表
     * @param ResponseInterface $response
     * @return array
     */
    public function parseSearchSuggestResponse(ResponseInterface $response){
        $res = (string) $response->getBody();
        $res = json_decode($res,true);
        return is_array($res) ? $res : [];
    }


    /**
     * 电影列表
     * @param ResponseInterface $response
     * @return array
     */
    public function parseListResponse(ResponseInterface $response){
        $res = (string) $response->getBody();
        $res = json_decode($res,true);
        return is_array($res) && isset($res['subjects']) ? $res['subjects'] : [];
    }


    /**
     * 解析详情结果
     * @param ResponseInterface $response
     * @return array
     */
    public function parseDetailResponse(ResponseInterface $response) {
        $html = (string) $response->getBody();

        $ql = QueryList::getInstance();
        $play_urls = $ql->html($html)->rules([
            'link'=>['a.playBtn','href','a'],
            'type'=>['a.playBtn','text','a'],
        ])->query()->getData(function ($item) {
            $item['link'] = str_replace('https://www.douban.com/link2/?url=', '', $item['link']);
            return $item;
        })->all();


        $rt = $ql->find('[type="application/ld+json"]')->text();
        $rt = preg_replace("/\n|\s{2,}/", '', $rt);
        $detail = json_decode($rt, true);
        if (is_array($detail) && !empty($detail)) {
            $detail['interest_sectl'] = $ql->find('#interest_sectl')->html();
            $detail['interest_sectl'] = strip_tags($detail['interest_sectl'], '<div> <span> <strong>');

            $info = $ql->find('#info')->html();
            $detail['info'] = strip_tags($info, '<span> <br>');

            foreach ($play_urls as $key => $play_url) {
                if ($play_url['link'] == 'javascript: void 0;') {
                    unset($play_urls[$key]);
                }
            }
            if (empty($play_urls)) {
                $play_urls = $ql->find('body > script[src^="https://img3.doubanio.com/misc/mixed_static/"]:eq(0)')->src;
                $play_urls = str_replace(['https://img3.doubanio.com/misc/mixed_static/', '.js'], ['', ''], $play_urls);
            }
            $detail['play_urls'] = $play_urls;
        }



//        $res = $ql->rules([
//            'info' => ['#info', 'html', 'a'],
//            'mainpic' => ['#mainpic > a > img', 'src'],
//            'interest_sectl' => ['#interest_sectl', 'html','a'],
//            'detail' => ['.related-info #link-report', 'text','p br'],
//            'title' => ['h1', 'text'],
//        ])->query()->getData(function ($item){
//            $item['detail'] = preg_replace('/\s{2,}/', '', $item['detail']);
//            return $item;
//        })->all();


        return $detail;
    }


    /**
     * 电影列表
     * @param ResponseInterface $response
     * @return array
     */
    public function parsePlayUrlJsResponse(ResponseInterface $response){
        $html = (string) $response->getBody();
        $content = preg_replace('/\s+/', '', $html);

        preg_match('/varsources=\{\};(.*?)\$\(\'.playBtn\'\)\.click/', $content, $res);
        $content = preg_replace('/sources\[\d+\]=/', '', $res[1]);
        $res = explode(',];', $content);

        $sources = [];
        foreach ($res as $value) {
            if (empty($value)) {
                continue;
            }
            $value = $value. ']';
            $value = str_replace(['play_link:"', 'ep:"'],['"play_link":"', '"ep":"'], $value);
            $value = json_decode($value, true);
            if (empty($value)) {
                continue;
            }
            $sources[] = $value;
        }

        return $sources;
    }


    /**
     * 解析排行榜结果
     * @param ResponseInterface $response
     * @return array
     */
    public function parseChartListResponse(ResponseInterface $response) {
        $html = (string) $response->getBody();

        $ql = QueryList::getInstance();

        // 新片排行榜
        $res['new'] = $ql->html($html)->rules([
            'cover' => ['div.article > div.indent table a.nbg > img', 'src',],
            'href' => ['div.article > div.indent table a.nbg', 'href'],
            'title' => ['div.article > div.indent table tr td div.pl2 > a', 'text'],
            'play' => ['div.article > div.indent table tr td div.pl2 > span', 'text'],
            'summary' => ['div.article > div.indent table tr td div.pl2 > p.pl', 'text'],
            'star' => ['div.article > div.indent table tr td div.pl2 > div.star > .rating_nums', 'text'],
        ])->query()->getData(function ($item) {
            $item['play'] = isset($item['play']) && !empty(trim($item['play']));
            $item['title'] = preg_replace("/\s{2,}/", ' ', $item['title']);
            return $item;
        })->all();

        // 周排行榜
        $res['week'] = $ql->rules([
            'href' => ['#listCont2 > li > div.name > a', 'href'],
            'title' => ['#listCont2 > li > div.name > a', 'text'],
        ])->query()->getData(function ($item) {
            preg_match('/(\d+)/', $item['href'],$r);
            $item['id'] = $r[1];
            return $item;
        })->all();


        // 北美票房榜
        $res['north_america'] = $ql->rules([
            'href' => ['#listCont1 > li > div.box_chart > a', 'href'],
            'title' => ['#listCont1 > li > div.box_chart > a', 'text'],
        ])->query()->getData(function ($item) {
            preg_match('/(\d+)/', $item['href'],$r);
            $item['id'] = $r[1];
            return $item;
        })->all();

        return $res;
    }


    /**
     * 解析剧照结果
     * @param ResponseInterface $response
     * @return array
     */
    public function parseDetailPhotosResponse(ResponseInterface $response) {
        $html = (string) $response->getBody();
        $ql = QueryList::getInstance();
        $res = $ql->html($html)->rules([
            'src'=>['.poster-col3 > li > div.cover > a >img','src'],
        ])->queryData();
        return $res;
    }


    /**
     * @param $uri
     * @param null $body
     * @param string $method
     * @param array $headers
     * @param bool $async
     * @return \GuzzleHttp\Promise\PromiseInterface|mixed|\Psr\Http\Message\ResponseInterface
     */
    public function request($uri, $body = null, $method = 'get', $headers = [], $async = false){
        $request = new Request($method, $uri, $headers, $body);
        $client = new Client(['timeout'  => 3.0,]);

        try {
            if ($async) {
                return $client->sendAsync($request);
            }
            return $client->send($request);
        } catch (GuzzleException $exception) {
            $this->error = $exception->getMessage();
            return false;
        }
    }
}
